package com.gf.framework.redis.core;

import lombok.AllArgsConstructor;

import java.time.Duration;
import java.util.Random;
import java.util.Stack;
import java.util.concurrent.TimeUnit;

/**
 * 缓存过期Holder
 *
 */
public class CacheExpireHolder {

    @AllArgsConstructor
    private static class Node {
        private long expire;
        private TimeUnit timeUnit;
        private long range;

        long getExpireMillis() {
            long timeOut = timeUnit.toMillis(expire);
            long timeOutRange = timeUnit.toMillis(range);
            if (timeOutRange != 0) {
                Random random = new Random();
                timeOut += (random.nextLong() % timeOutRange);
            }

            return timeOut;
        }
    }

    /**
     * CacheExpire有可能存在级联调用，因此需要用栈来保障顺序
     */
    private static final ThreadLocal<Stack<Node>> TIME_LOCAL = new ThreadLocal<>();

    /**
     * 获取当前方法失效时间（毫秒）
     */
    public static long get() {
        Stack<Node> stack = TIME_LOCAL.get();
        if (stack == null || stack.isEmpty()) {
            return -1;
        }
        return stack.peek().getExpireMillis();
    }


    /**
     * 设置当前方法对应的缓存失效时间（秒）
     */
    public static void set(long expire, TimeUnit timeUnit, long range) {
        Stack<Node> stack = TIME_LOCAL.get();
        if (stack == null) {
            stack = new Stack<>();
            TIME_LOCAL.set(stack);
        }
        stack.push(new Node(expire, timeUnit, range));
    }

    public static void remove() {
        Stack<Node> stack = TIME_LOCAL.get();
        if (stack == null) {
            return;
        }

        if (stack.isEmpty()) {
            TIME_LOCAL.remove();
        }
        else {
            stack.pop();
        }
    }
}
